//
//  CLBuletoothPrivateProtocolTool.m
//  toroBracelet
//
//  Created by 丁益 on 16/11/14.
//  Copyright © 2016年 celi. All rights reserved.
//

#import "CLBuletoothPrivateProtocolTool.h"
#import "CLBuleToothTool.h"
#import "CLCrc16.h"
#import "NSString+Extension.h"

#define delaySendWaitTime   20.0  //发送数据等待接收数据超时

uint8_t global_reponse_buffer[GLOBAL_RESPONSE_BUFFER_SIZE];
/* L1 send sequence id*/
uint16_t L1_sequence_id = 0;

/*
 * define a single response buffer
 * used to store response package triggered while sending
 */
static struct Response_Buff_Type_t g_ack_package_buffer =
{
    0,0,0
};
static L1_Send_Content * g_next_L1_send_content_buffer = NULL;
static L1_Send_Content sendContent[MAX_SEND_TASK];
static L1_Header_Schedule_type_t L1_header_need_schedule = {NULL,0};

/* register wait response package*/
static L1_Send_Content* current_package_wait_response = NULL;

static RECEIVE_STATE receive_state = WAIT_START;
static uint8_t received_buffer[GLOBAL_RECEIVE_BUFFER_SIZE];
static uint16_t received_content_length = 0;
static uint16_t length_to_receive;

static SEND_TASK_TYPE_T current_task_type = TASK_NONE;
static SEND_TASK_TYPE_T next_task_type = TASK_NONE;

//定义一个全局指针变量用于保存当前类的地址
CLBuletoothPrivateProtocolTool  *OCp = NULL;

@interface CLBuletoothPrivateProtocolTool()<CLBuleToothToolDelegate>

@property (nonatomic, strong) CLBuleToothTool *buleToothTool;
@property (nonatomic, strong) NSTimer *delaySendWaitTimer;

@end


@implementation CLBuletoothPrivateProtocolTool

- (void)creatBuleToothTool{
    
    CLBuleToothTool *buleToothTool = [CLBuleToothTool sharedBuleToothTool];
    buleToothTool.delegate = self;
    
    
    
    self.buleToothTool = buleToothTool;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self creatBuleToothTool];
        OCp = self;
    }
    return self;
}

- (void)dealloc {
    
    
    DLog(@"dealloc---");
}

Byte global_L1_header_buffer[L1_HEADER_SIZE];


/**
 *  发送数据
 */
- (void)sendBleData:(L2_Send_Content *) L2sendData dataLength:(NSInteger) length receiveAskBlock:(askBlock)receiveAskblock receiveResultBlock:(resultBlock)receiveResultBlock {

    self.receiveAskBlock = receiveAskblock;
    self.receiveResultBlock = receiveResultBlock;

    //判断蓝牙是否还在连接
    if ([self.buleToothTool isConnected] ) {
        DLog(@"ble 连接了");
    } else {
        DLog(@"ble 没有连接");
        return;
    }
    
    // 发送数据
    SEND_STATUS sendStatus;
    sendStatus = L1_send(L2sendData, no_follow_page);
    if (sendStatus != SEND_SUCCESS) {
        DLog(@"蓝牙数据发送失败----------");
    }
}


#pragma mark - 定时器
/**
 *  接收应答超时
 */
- (void)delaySendWaitTimerDeal:(NSTimer*)timer{
//    NSString *str = [NSString stringWithFormat:@"接收应答超时-----超时时间%fs",delaySendWaitTime];
    if (OCp.receiveAskBlock) {
         OCp.receiveAskBlock(SEND_FAIL);
    }
    
    [self stopDelaySendWaitTimer];
}

- (void)creatDelaySendWaitTimer{
    
    //开启一个等待应答定时器
//    if (self.delaySendWaitTimer) {
//        return;
//    }
    [self stopDelaySendWaitTimer];
    
    self.delaySendWaitTimer = [NSTimer scheduledTimerWithTimeInterval:delaySendWaitTime target:self selector:@selector(delaySendWaitTimerDeal:) userInfo:nil repeats:NO];
}


-(void)stopDelaySendWaitTimer{
    
    if (self.delaySendWaitTimer) {
        [self.delaySendWaitTimer invalidate];
        self.delaySendWaitTimer = nil;
    }
}



#pragma mark -蓝牙代理
- (void)buleToothTool:(CLBuleToothTool *)buleToothTool didReceiveStr:(NSString *)str{
    
    DLog(@"接收到的数据--%@",str);
    Byte receData[20] = {0};
    unsigned int receDataLength = 0;
    
    [NSString stringToHex:str hexData:receData writeLenght:&receDataLength];
    
    receiveDataDeal(receData, receDataLength);
}

#pragma mark -C语言处理部分
/* new_task_type shows where call this function*/
void async_send(void * para,uint16_t event_size,SEND_TASK_TYPE_T new_task_type)
{
   
    if(current_task_type == TASK_NONE) {
        current_task_type = new_task_type;
    } else {
        if((current_task_type == TASK_ACK) && (new_task_type == TASK_DATA) && (L1_header_need_schedule.isUsed == 1)) {//get a data send request while no buffer to send ack
            g_next_L1_send_content_buffer = *((L1_Send_Content **)para);
            next_task_type = TASK_DATA;
            return;
        } else if((current_task_type == TASK_DATA) && (new_task_type == TASK_ACK)) {
            next_task_type = TASK_ACK;
            return;
        }
    }
    
    uint16_t sendLen = 0;
    uint8_t * currentSendPointer = NULL;
    L1_Send_Content * content = NULL;
    
    if(current_task_type == TASK_ACK) {
    
        if(g_ack_package_buffer.isUsed == 1) {
            currentSendPointer = (uint8_t *)construct_response_package(g_ack_package_buffer.sequence_id,(g_ack_package_buffer.check_success == 1) ?true:false );
            sendLen = L1_HEADER_SIZE;
            if ([OCp.buleToothTool writeWithByte:currentSendPointer sendLength:sendLen] == NO) {
                if (OCp.receiveAskBlock) {
                    OCp.receiveAskBlock(SEND_NO_WRITE_SEVERS);
                }
                return;
            }
            //set task content
            current_task_type = TASK_NONE;
            next_task_type = TASK_NONE;
            g_ack_package_buffer.isUsed= 0;
        }
        return;
    }
    
    
    if(current_task_type == TASK_NONE) {
        return; //error condition
    }
    
    content =  *((L1_Send_Content **)para);

    SEND_CONTENT_TYPE_T sendContentType = CONTENT_NONE;
    /***********************************************************
    * Order :header content ack
    ************************************************************/
    while (1) {
    
        //first need to check header send request
        if(L1_header_need_schedule.isUsed == 1) {
            currentSendPointer = global_L1_header_buffer;
            sendLen = L1_HEADER_SIZE;
            sendContentType = CONTENT_HEADER;
        } else {
            //check other content
            if (content ->contentLeft != 0) {
                sendLen = ( content->contentLeft > BLE_SEND_MAX_LENGTH ) ? BLE_SEND_MAX_LENGTH : (content->contentLeft);
                currentSendPointer = (content->content + (content->length - content->contentLeft));
                sendContentType = CONTENT_DATA;
            } else {
                sendContentType = CONTENT_NONE;
            }
        }
        
        //first check if data is send complete
        if(sendContentType == CONTENT_NONE) {
            break; //which means send data complete
        }
        
        
        if ([OCp.buleToothTool writeWithByte:currentSendPointer sendLength:sendLen] == NO) {
            if (OCp.receiveAskBlock) {
                OCp.receiveAskBlock(SEND_NO_WRITE_SEVERS);
            }
            return;
        }
        
        //do flag
        switch(sendContentType) {
            case CONTENT_NONE:
                break;
                
            case CONTENT_HEADER: //mark header send complete
                if(L1_header_need_schedule.isUsed == 1) {
                    
                    L1_header_need_schedule.isUsed = 0;
                    memset(global_L1_header_buffer,0,L1_HEADER_SIZE);
                }
                break;
                
            case CONTENT_DATA:
                content ->contentLeft -= sendLen;
                if(content ->contentLeft == 0) { //send complete & will register wait
                    //set task content
                    current_task_type = TASK_NONE;
                    //begin to wait package response
                    register_wait_response(content);
                    //start timer wait for response
                    //? app_timer_start(delay_send_wait_timer,RESEND_DELAY,(void *)content);
                    [OCp creatDelaySendWaitTimer];
                }
                break;
                
            case CONTENT_ACK:
                if(g_ack_package_buffer.isUsed == 1) { //send ack package
                    //set task content
                    current_task_type = TASK_NONE;
                    g_ack_package_buffer.isUsed = 0;
                }
                break;
                
            default:
                break;
        }
    }
}


/* Schedule next package to be send after prev package send success*/
void schedule_async_send(void * contenxt,SEND_TASK_TYPE_T task)
{
    if(task == TASK_DATA) { //may be comes from data (send & resend) or (send complete callback)
        L1_Send_Content * data_content = (L1_Send_Content *)contenxt;
        if(data_content->contentLeft != 0) {
            //?app_timer_stop(delay_send_wait_timer);
            [OCp stopDelaySendWaitTimer];
        }
        async_send(&data_content,sizeof(L1_Send_Content *),TASK_DATA);
    } else if (task == TASK_ACK) {
        struct Response_Buff_Type_t * ack_content = (struct Response_Buff_Type_t *)contenxt;
        async_send(&ack_content,sizeof(struct Response_Buff_Type_t *),TASK_ACK);
        
    } else {//task none
       
    }
}


/*
 * L1 send content implementation
 * para description:
 * content->content
 * content->callback
 * content->length
 * isfollow_page  是否有后续包
 */
SEND_STATUS L1_send(L2_Send_Content * content , Is_follow_page isfollow_page)
{
    
    if(!content) {
        return SEND_FAIL;
    }
    
    uint32_t i = 0;

    /*fill header*/
    global_L1_header_buffer[L1_HEADER_MAGIC_POS] = L1_HEADER_MAGIC;           /* Magic */
    if(isfollow_page == have_follow_page){
        global_L1_header_buffer[L1_HEADER_PROTOCOL_VERSION_POS] = L1_HEADER_VERSION|L1_HEADER_FOLLOW_PACKAGE;       /* protocol version */
        
    } else {
        global_L1_header_buffer[L1_HEADER_PROTOCOL_VERSION_POS] = L1_HEADER_VERSION;       /* protocol version */
    }
    global_L1_header_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] = (content->length >> 8 & 0xFF);    /* length high byte */
    global_L1_header_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] = (content->length & 0xFF);      /* length low byte */
    /*cal crc*/
    uint16_t crc16_ret = bd_crc16(0,content->content,content->length);
    global_L1_header_buffer[L1_HEADER_CRC16_HIGH_BYTE_POS] = ( crc16_ret >> 8) & 0xff;
    global_L1_header_buffer[L1_HEADER_CRC16_LOW_BYTE_POS] = crc16_ret & 0xff;
    
    //sequence id
    global_L1_header_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] = (L1_sequence_id >> 8) & 0xff;
    global_L1_header_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] = L1_sequence_id & 0xff;
    
    //prepare for send L2 content
    sendContent[i].callback  =  content->callback;
    sendContent[i].content   =  content->content;
    sendContent[i].length  = content->length;
    sendContent[i].contentLeft  = content->length;
    sendContent[i].resendCount = 0;
    sendContent[i].sequence_id = L1_sequence_id;
    
    //every time send a package,increase L1_sequence_id, whether it's success or not
    L1_sequence_id ++;
    
    //register need to schedule header
    L1_header_need_schedule.isUsed = 1;
    L1_header_need_schedule.content = &sendContent[i];
    
    //schedule async send
    schedule_async_send(&sendContent[i],TASK_DATA);
    
    return SEND_SUCCESS;
}

/* Whole package resend */
// 1.应答超时重新发送数据包
SEND_STATUS L1_resend_package(L1_Send_Content * content)
{
    
    if(!content) {
        return SEND_FAIL;
    }
    
    /*fill header*/
    global_L1_header_buffer[L1_HEADER_MAGIC_POS] = L1_HEADER_MAGIC;           /* Magic */
    global_L1_header_buffer[L1_HEADER_PROTOCOL_VERSION_POS] = L1_HEADER_VERSION;       /* protocol version */
    global_L1_header_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] = (content->length >> 8 & 0xFF);    /* length high byte */
    global_L1_header_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] = (content->length & 0xFF);      /* length low byte */
    /*cal crc*/
    uint16_t crc16_ret = bd_crc16(0,content->content,content->length);
    global_L1_header_buffer[L1_HEADER_CRC16_HIGH_BYTE_POS] = ( crc16_ret >> 8) & 0xff;
    global_L1_header_buffer[L1_HEADER_CRC16_LOW_BYTE_POS] = crc16_ret & 0xff;
    
    //sequence id
    global_L1_header_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] = (L1_sequence_id >> 8) & 0xff;
    global_L1_header_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] = L1_sequence_id & 0xff;
    
    //prepare for send L2 content
    content->contentLeft = content->length;
    content->sequence_id = L1_sequence_id;
    //every time send a package,increase L1_sequence_id, whether it's success or not
    L1_sequence_id ++;
    
    //register need to schedule header
    L1_header_need_schedule.isUsed = 1;
    L1_header_need_schedule.content = content;
    

    
    //schedule async send
    schedule_async_send(content,TASK_DATA);
    return SEND_SUCCESS;
}


/* direct send response package without any sync op*/
static L1Header_t* construct_response_package(uint16_t sequence_id, bool check_success)
{
    static L1Header_t response_header;
    L1_version_value_t version_ack;
    
    
    response_header.magic = L1_HEADER_MAGIC;
    
    version_ack.version_def.version = L2_HEADER_VERSION;
    version_ack.version_def.ack_flag = 1;
    version_ack.version_def.err_flag = (check_success ? 0 : 1);
    version_ack.version_def.reserve = 0;
    
    response_header.version =  version_ack.value;
    response_header.payload_len = 0;
    response_header.crc16 = 0;
    response_header.sequence_id = ((sequence_id & 0xFF) << 8) | ((sequence_id >> 8) & 0xFF); //big engian
    
    return &response_header;
}

/**
 *  返回应答包
 */
void L1_receive_response(uint16_t sequence_id, bool check_success)
{
    //just use the new response request update the older one
    g_ack_package_buffer.check_success = (check_success == true) ? 1 :0;
    g_ack_package_buffer.sequence_id = sequence_id;
    g_ack_package_buffer.isUsed = 1;
    
    schedule_async_send(&g_ack_package_buffer,TASK_ACK);
}

/* check the crc16 value for the received package*/
static crc_check_result L1_crc_check(uint16_t crc_value,uint8_t *data,uint16_t length)
{
    uint16_t crc = bd_crc16(0x0000,data,length);
    if(crc == crc_value) {
        return CRC_SUCCESS;
    }
    return CRC_FAIL;
}

/**@snippet [Handling the data received over BLE] */
static void register_wait_response(L1_Send_Content * content)
{
    current_package_wait_response = content;
}

/* If receive response package call this function */
// 1.应答错误重新发送数据包
static void response_package_handle(uint16_t sequence_id,uint8_t crc_check)
{
    SEND_STATUS err_code;
    
//    SendCompletePara sendPara;
    if(!current_package_wait_response) {
        return;
    }
    
    if(current_package_wait_response->sequence_id == sequence_id ) {
        
        [OCp stopDelaySendWaitTimer];
        if( crc_check == CRC_SUCCESS) { //应答包正确
            current_package_wait_response->isUsed = 0;
            if(current_package_wait_response->callback) {
                current_package_wait_response->callback(SEND_SUCCESS);
            }
            
            if (OCp.receiveAskBlock) {
                OCp.receiveAskBlock(SEND_SUCCESS);
            }
            
        } else { //error resend
            
            if(current_package_wait_response->resendCount >= 3) {
                
                current_task_type = TASK_NONE;
                next_task_type = TASK_NONE;
                current_package_wait_response->isUsed = 0;
                
                if(current_package_wait_response->callback) {
                    current_package_wait_response->callback(SEND_FAIL);
                }
                
                if (OCp.receiveAskBlock) {
                    OCp.receiveAskBlock(SEND_FAIL);
                }
                //? clear_private_parameter();
                
            } else {

                current_package_wait_response->resendCount++;
                err_code = L1_resend_package(current_package_wait_response);
                if(err_code != SEND_SUCCESS) {
                    
                    current_package_wait_response->isUsed = 0;
                    if(current_package_wait_response->callback) {
                        current_package_wait_response->callback(SEND_FAIL);
                    }
                }
            }
        }
    }
}

void receiveDataDeal(Byte *receData, unsigned int receDataLength)
{
    L1_version_value_t inner_version;
    
    switch (receive_state) {
        case WAIT_START: // we need package start
            if(receData[0] != L1_HEADER_MAGIC) {
                //not a start package, so just igore
                break;
            }

            //get correct header
            received_content_length = 0;
            memcpy(&received_buffer[received_content_length],receData,receDataLength);
            received_content_length = receDataLength;
            
            length_to_receive = (received_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] | (received_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] << 8)) + L1_HEADER_SIZE;
            length_to_receive -= receDataLength;
            
            if(length_to_receive <= 0) { // just one package
                
                DLog(@"收到应答包----------------\r\n");
                
                inner_version.value = received_buffer[L1_HEADER_PROTOCOL_VERSION_POS];
                if(inner_version.version_def.ack_flag == RESPONSE_PACKAGE) { //response package
                    receive_state = WAIT_START; //restart receive state machine
                    response_package_handle((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),inner_version.version_def.err_flag);
                    return;
                }
                
                //data package
                receive_state = MESSAGE_RESOLVE;
                received_content_length = 0;
                
                uint16_t crc16_value = (received_buffer[L1_HEADER_CRC16_HIGH_BYTE_POS] << 8 | received_buffer[L1_HEADER_CRC16_LOW_BYTE_POS]);
                if(L1_crc_check(crc16_value,received_buffer+L1_HEADER_SIZE,(received_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] | (received_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] << 8))) == CRC_SUCCESS) { //check crc for received package
                    
                    //send response
                    L1_receive_response((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),true);
                    /*throw data to uppder layer*/
                    L2_frame_resolve(received_buffer+L1_HEADER_SIZE,(received_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] | (received_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] << 8)),&receive_state);
                } else { //receive bad package
                    //restart receive state machine
                    receive_state = WAIT_START;
                    
                    //send response
                    L1_receive_response((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),false);
                    return;
                }
            } else { // more than one package
                receive_state = WAIT_MESSAGE;
            }
            break;
        case WAIT_MESSAGE:  //等待接收多包数据完成
            
            memcpy(&received_buffer[received_content_length],receData,receDataLength);
            received_content_length += receDataLength;
            length_to_receive = length_to_receive - receDataLength;
            
            //接收完成
            if(length_to_receive <= 0) {
                
                DLog(@"数据接收完成-----");
                /* Stop timer */
                //? app_timer_stop(receive_time_out_timer);
                inner_version.value = received_buffer[L1_HEADER_PROTOCOL_VERSION_POS];
                
                if(inner_version.version_def.ack_flag == RESPONSE_PACKAGE) { //response package
                    receive_state = WAIT_START; //restart receive state machine
                    response_package_handle((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),inner_version.version_def.err_flag);
                    return;
                }
                
                receive_state = MESSAGE_RESOLVE;
                received_content_length = 0;
                
                uint16_t crc16_value = (received_buffer[L1_HEADER_CRC16_HIGH_BYTE_POS] << 8 | received_buffer[L1_HEADER_CRC16_LOW_BYTE_POS]);
                if(L1_crc_check(crc16_value,received_buffer+L1_HEADER_SIZE,(received_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] | (received_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] << 8))) == CRC_SUCCESS) { //check
                    //send response
                    L1_receive_response((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),true);
                    /*throw data to uppder layer*/
                    L2_frame_resolve(received_buffer+L1_HEADER_SIZE,(received_buffer[L1_PAYLOAD_LENGTH_LOW_BYTE_POS] | (received_buffer[L1_PAYLOAD_LENGTH_HIGH_BYTE_POS] << 8)),&receive_state);
                } else { //receive bad package
                    //restart receive state machine
                    receive_state = WAIT_START;
                    
                    //send response
                    L1_receive_response((received_buffer[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (received_buffer[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),false);
                    return;
                }
                
            } else {
                /* start receive time out timer */
                //?app_timer_start(receive_time_out_timer,RECEIVE_TIMEOUT,&receive_state);
            }
            
            break;
            
        case MESSAGE_RESOLVE:  //处理app发过来的应答包
            //in this situation , can only receive a ack package
            //Note: ack package must small than 20 bytes
            
            inner_version.value = receData[L1_HEADER_PROTOCOL_VERSION_POS];
            if(inner_version.version_def.ack_flag == RESPONSE_PACKAGE) { //response package
            
                response_package_handle((receData[L1_HEADER_SEQ_ID_LOW_BYTE_POS] | (receData[L1_HEADER_SEQ_ID_HIGH_BYTE_POS] << 8)),inner_version.version_def.err_flag);
            }
            break;

        default:
            break;
    }
}


/*
 * para introduction      解析命令
 * data                :      just the full of L2
 * content_length :      length of data
 * resolve_state   :     L1 receive data length
 */
static void L2_frame_resolve(uint8_t * data, uint16_t length,RECEIVE_STATE * resolve_state)
{
    //para check
    if((!data) || (length == 0)) {
        return ;
    }
    
    if (OCp.receiveResultBlock) {
        OCp.receiveResultBlock(data,length);
    }
    
    BLUETOOTH_COMMUNICATE_COMMAND command_id;
    uint8_t version_num;                 /* L2 version number */
    uint8_t first_key;                   /* first key of L2 payload*/
    uint16_t first_value_length;         /* length of first value */
    
    command_id      = (BLUETOOTH_COMMUNICATE_COMMAND)data[0];
    version_num = data[1];
    version_num = version_num;           /*current not use it*/
    first_key = data[2];
    first_value_length = (((data[3]<< 8) |data[4]) & 0x1FF);

    
    switch (command_id) {
        case FIRMWARE_UPDATE_CMD_ID:
            
            break;
            
        case SET_CONFIG_COMMAND_ID:
            
            break;
            
            //should not resolve bond command
        case BOND_COMMAND_ID:
            
            break;
            
        case NOTIFY_COMMAND_ID:
            
            break;
            
            
        case HEALTH_DATA_COMMAND_ID:
            
            break;
            
        case BLUETOOTH_LOG_COMMAND_ID:
            
            break;
        case TEST_COMMAND_ID:
            
            break;
            
        case CONTROL_COMMAND_ID: //控制命令
            
            break;
            
        case PAY_CARD_COMMAND_ID:
            
            break;
            
        case BAT_INFO_COMMAND_ID:
            
            break;
            
        default:
            break;
    }


    /*resolve complete and restart receive*/
    *resolve_state = WAIT_START;
}
@end
